package com.zzl.study.auth.security.authentication.context;

import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author: zhangzl
 * @date: 2024/6/6 14:17
 * @version: 1.0
 * @description: 自定义认证Token
 */
@Data
public class Authentication {

    /**
     * 权限
     */
    private List<OidcAuthority> authorities;

    /**
     * 详情
     */
    private Object details;

    /**
     * 是否认证
     */
    private boolean authenticated;

    /**
     * 认证主体
     */
    private OidcUser principal;

    /**
     * 认证客户端ID
     */
    private String authorizedClientRegistrationId;

    /**
     * 认证凭证
     */
    private Object credentials;

    /**
     * 认证主体名称
     */
    private String name;

    public static OAuth2AuthenticationToken to(Authentication authentication) {
        if (authentication == null) {
            return null;
        }
        DefaultOidcUser defaultOidcUser = OidcUser.to(authentication.getPrincipal());
        List<OidcAuthority> authorities = authentication.getAuthorities();
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        if (!CollectionUtils.isEmpty(authorities)) {
            for (OidcAuthority authority : authorities) {
                if (authority.getIdToken() != null) {
                    grantedAuthorities.add(OidcAuthority.toOidcUserAuthority(authority));
                } else {
                    grantedAuthorities.add(OidcAuthority.toSimpleGrantedAuthority(authority));
                }
            }
        }
        return new OAuth2AuthenticationToken(defaultOidcUser, grantedAuthorities, authentication.getAuthorizedClientRegistrationId());
    }

    public static Authentication of(OAuth2AuthenticationToken token) {
        if (token == null) {
            return null;
        }
        Authentication authentication = new Authentication();
        Collection<? extends GrantedAuthority> authorities = token.getAuthorities();
        if (!CollectionUtils.isEmpty(authorities)) {
            List<OidcAuthority> authoritiesList = new ArrayList<>();
            for (GrantedAuthority authority : authorities) {
                if (authority instanceof OidcUserAuthority) {
                    authoritiesList.add(OidcAuthority.ofOidcUserAuthority((OidcUserAuthority) authority));
                } else if (authority instanceof SimpleGrantedAuthority) {
                    authoritiesList.add(OidcAuthority.ofSimpleGrantedAuthority((SimpleGrantedAuthority) authority));
                }
            }
            authentication.setAuthorities(authoritiesList);
        }
        authentication.setAuthenticated(token.isAuthenticated());
        authentication.setDetails(token.getDetails());
        authentication.setPrincipal(OidcUser.of((DefaultOidcUser) token.getPrincipal()));
        authentication.setAuthorizedClientRegistrationId(token.getAuthorizedClientRegistrationId());
        authentication.setCredentials(token.getCredentials());
        authentication.setName(token.getName());
        return authentication;
    }

}
